use std::sync::Arc;
use std::time::Duration;
use anyhow::Result;
use tracing::{info, Level};
use tracing_subscriber::FmtSubscriber;

use protoactor_rs::actor::{Actor, ActorContext, ActorError};
use protoactor_rs::telemetry::{
    TelemetrySystem, TelemetryMiddleware, GlobalTelemetry,
    metrics::{Counter, Gauge, Histogram, Timer},
    tracing::{Tracer, Span, SpanContext, SpanStatus},
};
#[cfg(feature = "opentelemetry")]
use protoactor_rs::telemetry::otel::{OtelConfig, OtelTelemetrySystem};
use protoactor_rs::system::ActorSystem;

// 简单的计数器Actor
struct CounterActor {
    count: i32,
}

impl CounterActor {
    fn new() -> Self {
        Self { count: 0 }
    }
}

impl Actor for CounterActor {
    type Context = protoactor_rs::actor::DefaultActorContext;
    
    async fn receive(&self, ctx: &mut Self::Context, msg: Box<dyn std::any::Any + Send>) -> Result<(), ActorError> {
        if let Some(cmd) = msg.downcast_ref::<&str>() {
            match *cmd {
                "increment" => {
                    let mut this = self.clone();
                    this.count += 1;
                    ctx.respond(this.count);
                }
                "decrement" => {
                    let mut this = self.clone();
                    this.count -= 1;
                    ctx.respond(this.count);
                }
                "get" => {
                    ctx.respond(self.count);
                }
                _ => {
                    ctx.respond("Unknown command");
                }
            }
        }
        
        Ok(())
    }
}

impl Clone for CounterActor {
    fn clone(&self) -> Self {
        Self { count: self.count }
    }
}

#[tokio::main]
async fn main() -> Result<()> {
    // 设置日志
    let subscriber = FmtSubscriber::builder()
        .with_max_level(Level::INFO)
        .finish();
    tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed");
    
    // 创建遥测系统
    #[cfg(feature = "opentelemetry")]
    let telemetry_system: Arc<dyn TelemetrySystem> = {
        let config = OtelConfig {
            service_name: "protoactor-example".to_string(),
            service_version: "0.1.0".to_string(),
            endpoint: "http://localhost:4317".to_string(),
            trace_sample_ratio: 1.0,
            metrics_export_interval: 10,
            use_grpc: true,
        };
        
        Arc::new(OtelTelemetrySystem::new(config))
    };
    
    #[cfg(not(feature = "opentelemetry"))]
    let telemetry_system: Arc<dyn TelemetrySystem> = {
        use protoactor_rs::telemetry::metrics::MemoryMetrics;
        use protoactor_rs::telemetry::tracing::MemoryTracer;
        
        // 创建自定义遥测系统，基于内存实现
        struct MemoryTelemetrySystem {
            metrics: MemoryMetrics,
            tracer: MemoryTracer,
        }
        
        impl MemoryTelemetrySystem {
            fn new() -> Self {
                Self {
                    metrics: MemoryMetrics::new(),
                    tracer: MemoryTracer::new(),
                }
            }
        }
        
        impl TelemetrySystem for MemoryTelemetrySystem {
            fn init(&self) -> Result<(), String> {
                Ok(())
            }
            
            fn shutdown(&self) -> Result<(), String> {
                Ok(())
            }
            
            fn create_counter(&self, name: &str, description: &str, labels: &[&str]) -> Box<dyn Counter> {
                self.metrics.create_counter(name, description, labels)
            }
            
            fn create_gauge(&self, name: &str, description: &str, labels: &[&str]) -> Box<dyn Gauge> {
                self.metrics.create_gauge(name, description, labels)
            }
            
            fn create_histogram(&self, name: &str, description: &str, labels: &[&str], buckets: &[f64]) -> Box<dyn Histogram> {
                self.metrics.create_histogram(name, description, labels, buckets)
            }
            
            fn tracer(&self) -> Box<dyn Tracer> {
                Box::new(self.tracer.clone())
            }
        }
        
        Arc::new(MemoryTelemetrySystem::new())
    };
    
    // 初始化遥测系统
    let global_telemetry = GlobalTelemetry::new(telemetry_system.clone());
    global_telemetry.init()?;
    
    // 创建遥测中间件
    let telemetry_middleware = TelemetryMiddleware::new(telemetry_system.clone());
    
    // 创建Actor系统
    let system = ActorSystem::new();
    
    // 创建计数器
    let message_counter = telemetry_system.create_counter(
        "counter_messages",
        "Counter actor message count",
        &["message_type"],
    );
    
    // 创建直方图
    let operation_time = telemetry_system.create_histogram(
        "operation_time",
        "Time taken for counter operations",
        &["operation"],
        &[0.001, 0.005, 0.01, 0.05, 0.1],
    );
    
    // 创建并启动Actor
    let props = protoactor_rs::actor::Props::from_producer(|| CounterActor::new());
    let pid = system.spawn(props).await?;
    
    // 执行一些操作并记录指标
    for i in 0..5 {
        // 跟踪操作的整个生命周期
        let tracer = telemetry_system.tracer();
        let (span, ctx) = tracer.start_span("increment_operation", None);
        
        span.add_attribute("iteration", &i.to_string());
        
        // 记录消息计数
        message_counter.inc_with_labels(&["increment"]);
        
        // 使用计时器测量操作时间
        let timer = Timer::with_labels(operation_time.clone(), &["increment"]);
        
        // 执行操作
        let response = system.request::<i32>(&pid, "increment", Duration::from_secs(1)).await?;
        info!("Counter value after increment {}: {}", i+1, response);
        
        // 完成计时和跟踪
        timer.observe();
        span.end(None);
    }
    
    // 获取当前值
    let tracer = telemetry_system.tracer();
    let (span, _) = tracer.start_span("get_operation", None);
    
    message_counter.inc_with_labels(&["get"]);
    let timer = Timer::with_labels(operation_time.clone(), &["get"]);
    
    let response = system.request::<i32>(&pid, "get", Duration::from_secs(1)).await?;
    info!("Final counter value: {}", response);
    
    timer.observe();
    span.end(None);
    
    // 关闭遥测系统
    global_telemetry.shutdown()?;
    
    Ok(())
} 